package com.crm.system.service.impl.cluePoolManager;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.beust.jcommander.internal.Lists;
import com.crm.common.exception.BaseException;
import com.crm.common.exception.BizBaseException;
import com.crm.common.model.DhPageInfo;
import com.crm.common.model.Enum.StatusCodeEnum;
import com.crm.common.util.*;
import com.crm.model.dto.InsertFollowCallable;
import com.crm.model.entity.callCenter.CallForm;
import com.crm.model.entity.cluePoolManager.ClueContact;
import com.crm.model.entity.cluePoolManager.ClueFollow;
import com.crm.model.entity.cluePoolManager.ClueVisitRecord;
import com.crm.model.entity.contactManager.Contact;
import com.crm.model.entity.contactManager.ContactInformation;
import com.crm.model.entity.customerManager.Customer;
import com.crm.model.entity.customerManager.CustomerContactPerson;
import com.crm.model.entity.customerManager.SingleProductCustomerContact;
import com.crm.model.entity.followPlanManager.CpFollowPlan;
import com.crm.model.entity.sys.UserAccount;
import com.crm.model.qo.cluePoolManager.ClueFollowQO;
import com.crm.model.qo.cluePoolManager.CustomerOnlineFollowQO;
import com.crm.model.vo.cluePoolManager.*;
import com.crm.model.vo.contactManager.ContactInformationVO;
import com.crm.redis.mapper.ValueRMapper;
import com.crm.service.callCenter.CallFormDbService;
import com.crm.service.cluePoolManager.ClueContactDbService;
import com.crm.service.cluePoolManager.ClueFollowDbService;
import com.crm.service.cluePoolManager.ClueVisitRecordDbService;
import com.crm.service.contactManager.ContactDbService;
import com.crm.service.contactManager.ContactInformationDbService;
import com.crm.service.customerManager.CustomerContactPersonDbService;
import com.crm.service.customerManager.CustomerDbService;
import com.crm.service.customerManager.CustomerPoolDbService;
import com.crm.service.customerManager.SingleProductCustomerContactDbService;
import com.crm.service.followPlanManager.FollowPlanDbService;
import com.crm.service.sys.ImportFailureLogDbService;
import com.crm.service.sys.UserAccountDbService;
import com.crm.system.service.callCenter.CallFormService;
import com.crm.system.service.cluePoolManager.ClueFollowService;
import com.crm.system.service.contactManager.ContactInformationService;
import com.crm.system.service.contactManager.ContactService;
import com.crm.system.service.sys.ImportExportService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @ Author ：pym
 * @ Date   ：2021/1/8 13:04
 */
@Slf4j
@Service
public class ClueFollowServiceImpl implements ClueFollowService {
    @Autowired
    ClueFollowDbService clueFollowDbService;

    @Autowired
    ClueContactDbService clueContactDbService;

    @Autowired
    ClueVisitRecordDbService clueVisitRecordDbService;

    @Autowired
    CustomerContactPersonDbService customerContactPersonDbService;

    @Autowired
    CustomerPoolDbService customerPoolDbService;

    @Autowired
    ContactDbService contactDbService;

    @Autowired
    ContactService contactService;

    @Autowired
    ContactInformationDbService contactInformationDbService;

    @Autowired
    CallFormDbService callFormDbService;

    @Autowired
    CustomerDbService customerDbService;

    @Autowired
    FollowPlanDbService followPlanDbService;

    @Autowired
    SingleProductCustomerContactDbService singleProductCustomerContactDbService;

    @Autowired
    UserAccountDbService userAccountDbService;

    @Autowired
    ImportFailureLogDbService importFailureLogDbService;

    @Autowired
    ImportExportService importExportService;

    @Autowired
    ContactInformationService contactInformationService;

    @Autowired
    CallFormService callFormService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final String endpoint = "https://oss-cn-qingdao.aliyuncs.com";
    //        private static final String endpoint = "https://dcoss1.dcrm.cn";
    private static final String accessKeyId = "LTAI5tJAQ6jqvo3JkySW1Nwt";
    private static final String accessKeySecret = "itvmzbFWji33mIyrWvPmaCPiPqitYO";
    private static final String bucketName = "dc-ccoss";

    /**
     * 跟进报表的key,本周
     */
    public static final String WEEK_DAY_KEY = "follow_report:WEEK_DAYS";
    public static final String WEEK_FOLLOW_TABLE_KEY = "follow_report:week_follow_table:FOLLOW_TABLE_";
    public static final String WEEK_FOLLOW_NUMBER_ONLINE_KEY = "follow_report:week_follow_number_online:FOLLOW_NUMBER_ONLINE_";
    public static final String WEEK_FOLLOW_NUMBER_OFFLINE_KEY = "follow_report:week_follow_number_offline:FOLLOW_NUMBER_OFFLINE_";
    public static final String WEEK_FOLLOW_NUMBER_VISIT_KEY = "follow_report:week_follow_number_visit:FOLLOW_NUMBER_VISIT_";
    public static final String WEEK_FOLLOW_NUMBER_WECAT_KEY = "follow_report:week_follow_number_wecat:FOLLOW_NUMBER_WECAT_";
    public static final String WEEK_FOLLOW_NUMBER_ACVISIT_KEY = "follow_report:week_follow_number_acvisit:FOLLOW_NUMBER_ACVISIT_";
    public static final String WEEK_FOLLOW_NUMBER_MAIL_KEY = "follow_report:week_follow_number_mail:FOLLOW_NUMBER_MAIL_";
    public static final String WEEK_TOTAL_FOLLOW_NUMBER_KEY = "follow_report:week_total_follow_number:TOTAL_FOLLOW_NUMBER_";

    /**
     * 跟进报表的key,本月
     */
    public static final String MONTH_DAY_KEY = "follow_report:MONTH_DAYS";
    public static final String MONTH_FOLLOW_TABLE_KEY = "follow_report:month_follow_table:FOLLOW_TABLE_";
    public static final String MONTH_FOLLOW_NUMBER_ONLINE_KEY = "follow_report:month_follow_number_online:FOLLOW_NUMBER_ONLINE_";
    public static final String MONTH_FOLLOW_NUMBER_OFFLINE_KEY = "follow_report:month_follow_number_offline:FOLLOW_NUMBER_OFFLINE_";
    public static final String MONTH_FOLLOW_NUMBER_VISIT_KEY = "follow_report:month_follow_number_visit:FOLLOW_NUMBER_VISIT_";
    public static final String MONTH_FOLLOW_NUMBER_WECAT_KEY = "follow_report:month_follow_number_wecat:FOLLOW_NUMBER_WECAT_";
    public static final String MONTH_FOLLOW_NUMBER_ACVISIT_KEY = "follow_report:month_follow_number_acvisit:FOLLOW_NUMBER_ACVISIT_";
    public static final String MONTH_FOLLOW_NUMBER_MAIL_KEY = "follow_report:month_follow_number_mail:FOLLOW_NUMBER_MAIL_";
    public static final String MONTH_TOTAL_FOLLOW_NUMBER_KEY = "follow_report:month_total_follow_number:TOTAL_FOLLOW_NUMBER_";

    /**
     * 跟进报表的key,上月
     */
    public static final String LAST_MONTH_DAY_KEY = "follow_report:LAST_MONTH_DAYS";
    public static final String LAST_MONTH_FOLLOW_TABLE_KEY = "follow_report:last_month_follow_table:FOLLOW_TABLE_";
    public static final String LAST_MONTH_FOLLOW_NUMBER_ONLINE_KEY = "follow_report:last_month_follow_number_online:FOLLOW_NUMBER_ONLINE_";
    public static final String LAST_MONTH_FOLLOW_NUMBER_OFFLINE_KEY = "follow_report:last_month_follow_number_offline:FOLLOW_NUMBER_OFFLINE_";
    public static final String LAST_MONTH_FOLLOW_NUMBER_VISIT_KEY = "follow_report:last_month_follow_number_visit:FOLLOW_NUMBER_VISIT_";
    public static final String LAST_MONTH_FOLLOW_NUMBER_WECAT_KEY = "follow_report:last_month_follow_number_wecat:FOLLOW_NUMBER_WECAT_";
    public static final String LAST_MONTH_FOLLOW_NUMBER_ACVISIT_KEY = "follow_report:last_month_follow_number_acvisit:FOLLOW_NUMBER_ACVISIT_";
    public static final String LAST_MONTH_FOLLOW_NUMBER_MAIL_KEY = "follow_report:last_month_follow_number_mail:FOLLOW_NUMBER_MAIL_";
    public static final String LAST_MONTH_TOTAL_FOLLOW_NUMBER_KEY = "follow_report:last_month_total_follow_number:TOTAL_FOLLOW_NUMBER_";


    /**
     * 线索池详情-线索清单-跟进记录
     *
     * @param pageIndex ---页码
     * @param pageSize  ---分页大小
     * @param clueId    ---线索Id
     * @return
     */
    @Override
    public DhPageInfo<ClueFollowVO> selectClueFollowVOList(Integer pageIndex, Integer pageSize, String clueId) {
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        List<ClueFollowVO> clueFollowVOList = clueFollowDbService.selectClueFollowVOList(clueId);
        PageInfo<ClueFollowVO> pageInfo = new PageInfo<ClueFollowVO>(clueFollowVOList);
        return new DhPageInfo<ClueFollowVO>(pageInfo, clueFollowVOList);
    }

    /**
     * @param clueFollowQO 跟进参数
     * @return
     * @author wll
     * info 用户模块-我的线索池-线索清单-添加跟进 / 用户模块-客户管理-我的客户-跟进 / 用户模块-客户管理-单品客户-跟进
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class})
    public String addClueFollow(ClueFollowQO clueFollowQO) {
        Boolean result = false;
        String clueFollowId = "";
        String contactName = clueFollowQO.getContactName();
        String contactInformation = clueFollowQO.getContactInformation();
        //联系人姓名、联系人电话为空不添加跟进记录
        if (StringUtils.isNotBlank(contactName) && StringUtils.isNotBlank(contactInformation)) {
            UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
            String customerId = clueFollowQO.getCustomerId();
            Contact contact = new Contact();
            //从哪跳转到跟进页面（0：线索；1：客户）
            if ("0".equals(clueFollowQO.getSource())) {
                clueFollowQO.setFollowSource(0);//跟进来源
                //根据线索id、联系人名称和联系方式判重，是否插入线索联系人
                ClueContact clueContact = clueContactDbService.isInsertClueContact(clueFollowQO.getClueId(),
                        contactName, contactInformation);
                if (clueContact == null) {
                    //插入线索联系人记录
                    String clueContactId = this.insertClueContact(clueFollowQO, userAccount);
                    clueFollowQO.setClueContactId(clueContactId);
                } else {
                    clueFollowQO.setClueContactId(clueContact.getClueContactId());
                }
            } else if ("1".equals(clueFollowQO.getSource())) {
                CustomerContactPerson customerContactPersons = null;
                clueFollowQO.setFollowSource(1);//跟进来源
                /*if (StringUtils.isNotBlank(customerId) && StringUtils.isNotBlank(contactName) && StringUtils.isNotBlank(contactInformation)) {
                    //根据客户id、联系人名称和联系方式判重，是否插入客户联系人
                    customerContactPersons = customerContactPersonDbService.isInsertCustomerContactPerson(
                            customerId, contactName, contactInformation);
                }*/
                //根据客户id、联系人名称和联系方式判重，是否插入客户联系人
                customerContactPersons = customerContactPersonDbService.isInsertCustomerContactPerson(
                        customerId, contactName, contactInformation);
                //如果电话前面有0，去掉0再查一下
                if (customerContactPersons == null) {
                    if (contactInformation != null && contactInformation.startsWith("0")) {
                        contactInformation = contactInformation.substring(1, contactInformation.length());
                        customerContactPersons = customerContactPersonDbService.isInsertCustomerContactPerson(
                                customerId, contactName, contactInformation);
                    }
                }
                if (customerContactPersons == null && !"1".equals(clueFollowQO.getCustomerType())) {
                    //新增客户下的联系人
                    customerContactPersons = getCustomerContactPerson(clueFollowQO, userAccount);
                    if (customerContactPersons != null && !StringUtils.isBlank(customerContactPersons.getCustomerContactPersonId())) {
                        clueFollowQO.setClueContactId(customerContactPersons.getCustomerContactPersonId());
                    }
                    //根据联系人名称和联系方式判重，是否插入联系人管理
                /*Boolean isInsertContact = contactDbService.isInsertContact(contactName, contactInformation);
                if (!isInsertContact) {
                    //新增联系人管理的联系人
                    Contact contact = getContact(clueFollowQO, userAccount);
                    contactDbService.addContact(contact);
                }*/

                    //2021-03-10 isInsertCustomerContactPerson判重就可以，插入联系人管理不需要判重
                    //新增联系人管理的联系人
                    contact = getContact(clueFollowQO, userAccount);
                    contactDbService.addContact(contact);
                    clueFollowQO.setContactId(contact.getContactId());
                    List<ContactInformationVO> contactInformationList = contactService.getCustomerIdAndContactInformation(customerId, contactInformation, "");
                    if (contactInformationList == null || contactInformationList.size() <= 0) {
                        //新增联系方式
                        ContactInformation contactInformationPOJO = getContactInformation(userAccount, contactInformation, customerId, contact);
                        contactInformationDbService.addContactInformation(contactInformationPOJO);
                    }
                } else {
                    clueFollowQO.setClueContactId(customerContactPersons != null ? customerContactPersons.getCustomerContactPersonId() : "");
                    contact = contactDbService.getContactId(customerId, contactInformation, contactName);


                    String contactId = contact.getContactId();
                    if (contact != null && contactId != null) {
                        clueFollowQO.setContactId(contactId);
                    } else {
                        clueFollowQO.setContactId("");
                    }
                }

                if (contact != null && contact.getContactId() != null) {
                    //热力值加
                    Integer thermodynamicValue = contact.getThermodynamicValue();
                    if (thermodynamicValue == null) {
                        thermodynamicValue = 0;
                    }

                    //跟进次数+1
                    Integer followUpTimes = contact.getFollowUpTimes();
                    if (followUpTimes == null) {
                        followUpTimes = 0;
                    }
                    //跟进方式  1-线上电话；2-拜访 3-微信 4-线下电话 5-邮箱 6-陪访
                    if (clueFollowQO.getFollowWay() != 0) {
                        //拜访 10分  其他的5分
                        if (clueFollowQO.getFollowWay() == 2) {
                            thermodynamicValue += 10;
                        } else {
                            thermodynamicValue += 5;
                        }
                        followUpTimes += 1;
                    }

                    //向客户联系人表增加跟进次数
                    if (customerContactPersons != null) {
                        customerContactPersons.setFollowUpTimes(followUpTimes);
                        customerContactPersonDbService.updateCustomerContactPerson(customerContactPersons);
                    }

                    contact.setThermodynamicValue(thermodynamicValue);
                    contact.setFollowUpTimes(followUpTimes);
                    contact.setUpdatePeopleId(userAccount.getAccountId());
                    contact.setUpdateTm(new Date());
                    contactDbService.updateContact(contact);
                }

                //客户意向不为空，将客户设置成意向客户
                if (StringUtils.isNotBlank(clueFollowQO.getCustomerIntention())) {
                    Customer customer = new Customer();
                    customer.setCustomerId(customerId);
                    customer.setPotentialCustomers(1);
                    customer.setUpdatePeopleId(userAccount.getAccountId());
                    customer.setUpdateTm(new Date());
                    customerDbService.updateCustomerById(customer);
                }
                //增加跟进计划
                if (clueFollowQO.getNextPlanTime() != null) {
                    CpFollowPlan cpFollowPlan = new CpFollowPlan();
                    cpFollowPlan.setCpFollowPlanId(CommonUtils.getGUID());
                    cpFollowPlan.setCustomerId(customerId);
                    cpFollowPlan.setContactPerson(contactName);
                    cpFollowPlan.setContactPersonPhone(contactInformation);
                    cpFollowPlan.setPlanDate(clueFollowQO.getNextPlanTime());
                    //cpFollowPlan.setPlanStatus("0");
                    //cpFollowPlan.setDeleteStatus(Short.parseShort(String.valueOf(StatusCodeEnum.NORMAL_CODE.getState())));
                    cpFollowPlan.setCreatePeopleId(userAccount.getAccountId());
                    cpFollowPlan.setCreateTm(new Date());
                    cpFollowPlan.setUpdatePeopleId(userAccount.getAccountId());
                    cpFollowPlan.setUpdateTm(new Date());
                    followPlanDbService.addFollowPlan(cpFollowPlan);
                }
            } else if ("2".equals(clueFollowQO.getSource())) {
                clueFollowQO.setFollowSource(2);//跟进来源
                clueFollowQO.setCustomerId("");
                //单品客户联系方式针对所有账号唯一
                SingleProductCustomerContact singleProductCustomerContact
                        = singleProductCustomerContactDbService.isInsertSingleProductCustomerContact(contactInformation);
                if (singleProductCustomerContact == null) {
                    SingleProductCustomerContact singleProductCustomerContact1 = getSingleProductCustomerContact(clueFollowQO, userAccount);
                    clueFollowQO.setClueContactId(singleProductCustomerContact1.getSingleProductCustomerContactId());
                } else {
                    clueFollowQO.setClueContactId(singleProductCustomerContact.getSingleProductCustomerContactId());
                }

            }
            ClueFollow clueFollow = getClueFollow(clueFollowQO, userAccount);
            //类别为拜访 陪访 添加拜访表里数据
            if (clueFollowQO.getFollowWay() == 2 || clueFollowQO.getFollowWay() == 6) {//2-拜访 6-陪访
                //新增拜访记录
                String clueVisitVecordid = insertClueVisitVecord(clueFollowQO, userAccount);
                clueFollow.setVisitRecordId(clueVisitVecordid);//线索拜访表id
            }
            result = clueFollowDbService.addClueFollow(clueFollow);
            clueFollowId = clueFollow.getClueFollowId();
        }
        return clueFollowId;
    }

    /**
     * 单品客户联系人
     *
     * @param clueFollowQO 跟进参数
     * @param userAccount  账号
     * @return
     */
    private SingleProductCustomerContact getSingleProductCustomerContact(ClueFollowQO clueFollowQO, UserAccount userAccount) {
        SingleProductCustomerContact singleProductCustomerContact = new SingleProductCustomerContact();
        singleProductCustomerContact.setSingleProductCustomerContactId(CommonUtils.getGUID());
        singleProductCustomerContact.setContactName(clueFollowQO.getContactName());
        singleProductCustomerContact.setContactInformation(clueFollowQO.getContactInformation());
        singleProductCustomerContact.setContactPosition("3");
        singleProductCustomerContact.setCreatePeopleId(userAccount.getAccountId());
        singleProductCustomerContact.setCreateTm(new Date());
        singleProductCustomerContact.setUpdatePeopleId(userAccount.getAccountId());
        singleProductCustomerContact.setUpdateTm(new Date());
        singleProductCustomerContact.setDeleteStatus(Short.parseShort(String.valueOf(StatusCodeEnum.NORMAL_CODE.getState())));
        singleProductCustomerContact.setSingleProductCustomerId(clueFollowQO.getSingleProductCustomerId());
        singleProductCustomerContactDbService.insertSingleProductCustomerContact(singleProductCustomerContact);
        return singleProductCustomerContact;
    }

    /**
     * 联系方式记录
     *
     * @param userAccount        --账号信息
     * @param contactInformation --联系方式
     * @param customerId         --客户id
     * @param contact            --联系人管理表
     * @return {@link {com.crm.model.entity.contactManager.ContactInformation}}
     * @Author pym
     * @Date 2021/3/11 8:48
     */
    private ContactInformation getContactInformation(UserAccount userAccount, String contactInformation, String customerId, Contact contact) {
        ContactInformation contactInformationPOJO = new ContactInformation();
        contactInformationPOJO.setContactInformationId(CommonUtils.getGUID());
        contactInformationPOJO.setContactInformation(contactInformation);
        contactInformationPOJO.setContactType("跟进电话");
        contactInformationPOJO.setContactInformationType(0);
        contactInformationPOJO.setCreatePeopleId(userAccount.getAccountId());
        contactInformationPOJO.setCreateTm(new Date());
        contactInformationPOJO.setUpdatePeopleId(userAccount.getAccountId());
        contactInformationPOJO.setUpdateTm(new Date());
        contactInformationPOJO.setContactId(contact.getContactId());
        contactInformationPOJO.setCustomerId(customerId);
        contactInformationPOJO.setAbolishState(1);  //废止状态  1启动 2废止
        contactInformationPOJO.setDeleteStatus(Short.parseShort(String.valueOf(StatusCodeEnum.NORMAL_CODE.getState())));
        contactInformationPOJO.setCompanyId(userAccount.getCompanyId());
        return contactInformationPOJO;
    }

    /**
     * 联系人管理表记录
     *
     * @param clueFollowQO --跟进参数
     * @param userAccount  --账号信息
     * @return {@link {com.crm.model.entity.contactManager.Contact}}
     * @Author pym
     * @Date 2021/3/4 14:33
     */
    private Contact getContact(ClueFollowQO clueFollowQO, UserAccount userAccount) {
        Contact contact = new Contact();
        contact.setContactId(CommonUtils.getGUID());
        contact.setContactName(clueFollowQO.getContactName());
        contact.setContactInformation(clueFollowQO.getContactInformation());
        contact.setFollowUpTimes(0);
        contact.setCreatePeopleId(userAccount.getAccountId());
        contact.setCreateTm(new Date());
        contact.setUpdatePeopleId(userAccount.getAccountId());
        contact.setUpdateTm(new Date());
        contact.setDeleteStatus(Short.parseShort(String.valueOf(StatusCodeEnum.NORMAL_CODE.getState())));
        //contact.setContactState();
        //contact.setMemberGrade();
        //contact.setMergeState(0);
        contact.setContactNature(clueFollowQO.getCustomerType() != null ? Integer.parseInt(clueFollowQO.getCustomerType()) : 0);
        contact.setAbolishState(1);
        contact.setCustomerId(clueFollowQO.getCustomerId());
        contact.setAccountId(userAccount.getAccountId());
        contact.setCompanyId(userAccount.getCompanyId());
        return contact;
    }

    /**
     * 客户联系人记录
     *
     * @param clueFollowQO --跟进参数
     * @param userAccount  --账号信息
     * @return {@link {com.crm.model.entity.customerManager.CustomerContactPerson}}
     * @Author pym
     * @Date 2021/3/4 14:22
     */
    private CustomerContactPerson getCustomerContactPerson(ClueFollowQO clueFollowQO, UserAccount userAccount) {
        CustomerContactPerson customerContactPerson = new CustomerContactPerson();
        customerContactPerson.setCustomerContactPersonId(CommonUtils.getGUID());
        customerContactPerson.setContactName(clueFollowQO.getContactName());
        customerContactPerson.setContactInformation(clueFollowQO.getContactInformation());
        customerContactPerson.setFollowUpTimes(0);
        customerContactPerson.setCreatePeopleId(userAccount.getAccountId());
        customerContactPerson.setCreateTm(new Date());
        customerContactPerson.setUpdatePeopleId(userAccount.getAccountId());
        customerContactPerson.setUpdateTm(new Date());
        customerContactPerson.setDeleteStatus(Short.parseShort(String.valueOf(StatusCodeEnum.NORMAL_CODE.getState())));
        customerContactPerson.setAbolishState(1);
        //customerContactPerson.setContactState();
        customerContactPerson.setMergeState(0);
        customerContactPerson.setCustomerId(clueFollowQO.getCustomerId());
        customerContactPerson.setCompanyId(userAccount.getCompanyId());
        //新增客户下的联系人
        customerPoolDbService.addCustomerContactPerson(customerContactPerson);
        return customerContactPerson;
    }

    /**
     * 线索/客户跟进记录
     *
     * @param clueFollowQO 跟进参数
     * @param userAccount  账号信息
     * @return {@link {com.crm.model.entity.cluePoolManager.ClueFollow}}
     * @Author pym
     * @Date 2021/3/4 11:45
     */
    public ClueFollow getClueFollow(ClueFollowQO clueFollowQO, UserAccount userAccount) {
        ClueFollow clueFollow = new ClueFollow();
        BeanUtils.copyProperties(clueFollowQO, clueFollow);
        //处理数据
        clueFollow.setClueFollowId(CommonUtils.getGUID());//主键
        clueFollow.setCreatePeopleId(userAccount.getAccountId());
        clueFollow.setCompanyId(userAccount.getCompanyId());
        clueFollow.setCreateTm(new Date());
        clueFollow.setUpdatePeopleId(userAccount.getAccountId());
        clueFollow.setUpdateTm(new Date());
        //沟通时长（秒）
        if (clueFollowQO.getFollowWay() == 1) {//线上电话
            clueFollow.setCommunicationTime(clueFollowQO.getCommunicationTime());//沟通时长（秒） 页面秒
        } else {
            clueFollow.setCommunicationTime(clueFollowQO.getCommunicationTime() * 60);//沟通时长（秒） 页面分钟
        }
        //当followPurpose=1 (产品类别 1会员 2非会员) 当followPurpose=2(过程类别 1询问意向 2再次跟进 3成交 4意向关怀)
        if ("1".equals(clueFollowQO.getFollowPurpose())) {//1-跟进产品
            clueFollow.setFollowProduct(clueFollowQO.getFollowValue());
        } else {//2-过程管理
            clueFollow.setFollowProcess(clueFollowQO.getFollowValue());
        }
        return clueFollow;
    }

    public String insertClueVisitVecord(ClueFollowQO clueFollowQO, UserAccount userAccount) {
        ClueVisitRecord clueVisitRecord = new ClueVisitRecord();
        clueVisitRecord.setClueVisitRecordId(UUID.randomUUID().toString().replaceAll("-" , ""));
        if (clueFollowQO.getFollowWay() == 2) {
            clueVisitRecord.setType(1);//拜访
        } else {
            clueVisitRecord.setType(2);//陪访
        }

        clueVisitRecord.setVisitAddress(clueFollowQO.getVisitAddress());//===========拜访地址 类型为这个的时候 传这个参数
        clueVisitRecord.setAccompanyVisitPeople(clueFollowQO.getContactName());//拜访人or配方人
        clueVisitRecord.setContactPerson(clueFollowQO.getContactName());//联系人
        clueVisitRecord.setContactInformation(clueFollowQO.getContactInformation());//联系电话
        //沟通时长（秒）
        if (clueFollowQO.getFollowWay() == 1) {
            clueVisitRecord.setCommunicationTime(clueFollowQO.getCommunicationTime());//沟通时长（秒） 页面秒
        } else {
            clueVisitRecord.setCommunicationTime(clueFollowQO.getCommunicationTime() * 60);//沟通时长（秒） 页面分钟
        }
        clueVisitRecord.setVisitDetail(clueFollowQO.getFollowDetail());//详情
        clueVisitRecord.setUploadId(clueFollowQO.getAccountUploadId());//电话账号附件id
        clueVisitRecord.setMinUploadId(clueFollowQO.getMinUploadId());//电话时长附件id
        clueVisitRecord.setDeleteStatus(Short.parseShort("0"));
        clueVisitRecord.setCreatePeopleId(userAccount.getAccountId());//创建人
        //clueVisitRecord.setCreateTm(clueFollowQO.getFollowTm());//创建时间（跟进日期）
        clueVisitRecord.setCreateTm(new Date());
        clueVisitRecord.setUpdatePeopleId(userAccount.getAccountId());//更新人id
        clueVisitRecord.setUpdateTm(new Date());//更新时间
        //clueVisitRecord.setClueId(clueFollowQO.getClueId());//线索id
        if (!StringUtils.isBlank(clueFollowQO.getClueId())) {
            clueVisitRecord.setClueId(clueFollowQO.getClueId());//线索id
        } else {
            clueVisitRecord.setClueId("");//线索id
        }
        clueVisitRecord.setMainVisitor(clueFollowQO.getMainVisitor());//主拜访人
        clueVisitRecord.setAccompanyingPerson(clueFollowQO.getAccompanyingPerson());//陪访人
        clueVisitRecord.setCustomerId(clueFollowQO.getCustomerId());//客户id
        clueVisitRecord.setSingleProductCustomerId(clueFollowQO.getSingleProductCustomerId());//单品客户主键ID
        clueVisitRecord.setFollowSource(clueFollowQO.getFollowSource());//跟进来源
        if (clueVisitRecordDbService.insertClueVisitVecord(clueVisitRecord) > 0) {
            return clueVisitRecord.getClueVisitRecordId();
        } else {
            return "";
        }
    }

    private String insertClueContact(ClueFollowQO clueFollowQO, UserAccount userAccount) {
        ClueContact clueContact = new ClueContact();
        clueContact.setClueContactId(UUID.randomUUID().toString().replaceAll("-" , ""));
        clueContact.setContactName(clueFollowQO.getContactName());
        clueContact.setContactInformation(clueFollowQO.getContactInformation());
        clueContact.setClueId(clueFollowQO.getClueId());
        clueContact.setDeleteStatus(Short.parseShort("0"));
        clueContact.setCreatePeopleId(userAccount.getAccountId());
        clueContact.setCreateTm(new Date());
        clueContact.setUpdatePeopleId(userAccount.getAccountId());
        clueContact.setUpdateTm(new Date());
        if (clueContactDbService.insertClueContactInfo(clueContact) > 0) {
            return clueContact.getClueContactId();
        } else {
            return "";
        }
    }


    @Override
    public long selectClueFollowCountByPoolId(String cluePoolId) {
        long num = clueFollowDbService.selectClueFollowCountByPoolId(cluePoolId);
        return num;
    }

    @Override
    public List<ClueFollowContractVO> selectClueFollowListByCustomerId(String customerId) {
        List<ClueFollowContractVO> clueFollowVOList = new ArrayList<>();
        List<ClueFollow> clueFollowList = clueFollowDbService.selectClueFollowListByCustomerId(customerId);
        clueFollowList.stream().forEach(clueFollow -> {
            ClueFollowContractVO clueFollowContractVO = new ClueFollowContractVO();
            clueFollowContractVO.setClueFollowId(clueFollow.getClueFollowId());
            clueFollowContractVO.setFollowTm(clueFollow.getFollowTm());
            if (clueFollow.getFollowWay() != null) {
                switch (clueFollow.getFollowWay()) {
                    case 1:
                        clueFollowContractVO.setFollowWayName("线上电话");
                        break;
                    case 2:
                        clueFollowContractVO.setFollowWayName("拜访");
                        break;
                    case 3:
                        clueFollowContractVO.setFollowWayName("微信");
                        break;
                    case 4:
                        clueFollowContractVO.setFollowWayName("线下电话");
                        break;
                    case 5:
                        clueFollowContractVO.setFollowWayName("邮箱");
                        break;
                    case 6:
                        clueFollowContractVO.setFollowWayName("陪访");
                        break;
                    default:
                        break;
                }
            }
            clueFollowVOList.add(clueFollowContractVO);
        });
        return clueFollowVOList;
    }

    /**
     * 用户系统--客户管理>我的客户>跟进记录详情
     *
     * @param clueFollowId ---跟进记录主键
     * @param type         1:单品客户跟进详情
     * @return
     * @author yincuimei
     */
    @Override
    public ClueFollowVO selectClueFollowVOById(String clueFollowId, String type, Integer followWay) {
        //1:查询跟进记录表(cp_clue_follow)
        ClueFollowVO clueFollowVO = clueFollowDbService.selectClueFollowVOById(clueFollowId, type, followWay);
        if (clueFollowVO != null) {
            if (StringUtils.isBlank(clueFollowVO.getCustomerIntention())) {
                clueFollowVO.setCustomerIntention("0");//客户意向(百分比)
            }
            if (StringUtils.isBlank(clueFollowVO.getTag())) {
                clueFollowVO.setTag("");//标签
            }
            if (!StringUtils.isBlank(clueFollowVO.getCallRecord())) {//通话录音
                clueFollowVO.setCallRecord(getSecretUrl(clueFollowVO.getCallRecord()));
            }
        }
        return clueFollowVO;
    }

    /**
     * @Description: 生成oss签名url
     * @Param: [objectName] 地址
     * @Return: java.lang.String
     * @Author: lixq-f
     * @Date: 2021/6/28
     **/
    private static String getSecretUrl(String objectName) {
        if (StringUtils.isEmpty(objectName)) {
            return null;
        }

        OSS ossClient = null;
        try {
            if (objectName.contains("/home/cic/cic2000/tone/RecordFile")) {
                objectName = objectName.replace("/home/cic/cic2000/tone/RecordFile" , "RecFile");
            } else if (objectName.contains("http://118.190.175.96:8081/tone")) {
                objectName = objectName.replace("http://118.190.175.96:8081/tone" , "RecFile");
            } else if (objectName.contains("http://47.104.218.1896:8081/Rec")) {
                objectName = objectName.replace("http://47.104.218.1896:8081/Rec" , "RecFile");
            } else {
                return objectName;
            }
            // 创建OSSClient实例。
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            // 设置URL过期时间为1小时。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000);
            // 生成签名URL。
            URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            log.info("getSecretUrl:{}" , JSON.toJSONString(url));
            return url.toString();
        } catch (Exception e) {
            log.error("getSecretUrl error :{}" , e);
        } finally {
            // 关闭OSSClient。
            if (null != ossClient) {
                ossClient.shutdown();
            }
        }

        return null;
    }

    /**
     * 联系人详情-跟进记录查询-通过联系人id
     *
     * @param contactId 联系人id
     * @param dateType  thisWeek 本周  thisMonth 本月
     * @return
     */
    @Override
    public DhPageInfo<ContactDetailFollowVO> selectFollowByContactId(Integer pageIndex, Integer pageSize, String sortName, String sortOrder, String contactId, String dateType) {

        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }


        Integer dateUnit = 0;
        if (!StringUtils.isBlank(dateType)) {
            if ("thisWeek".equals(dateType)) {
                //本周
                dateUnit = 1;
            }
            if ("thisMonth".equals(dateType)) {
                //本月
                dateUnit = 2;
            }
        }

        List<ContactDetailFollowVO> followList = clueFollowDbService.selectFollowByContactId(contactId, dateUnit);

        for (ContactDetailFollowVO contactDetailFollowVO : followList) {
            if (!StringUtils.isBlank(contactDetailFollowVO.getCallRecord())) {
                String secretUrl = getSecretUrl(contactDetailFollowVO.getCallRecord());
                contactDetailFollowVO.setCallRecord(secretUrl);
            }
        }


        PageInfo<ContactDetailFollowVO> pageInfo = new PageInfo<ContactDetailFollowVO>(followList);
        return new DhPageInfo<ContactDetailFollowVO>(pageInfo, followList);
    }

    /**
     * 跟进记录
     *
     * @param clueFollowQO
     * @param pageIndex
     * @param pageSize
     * @param sort
     * @param sortOrder
     * @return
     */
    @Override
    public DhPageInfo<ClueFollowVO> selectClueFollowList(ClueFollowQO clueFollowQO, Integer pageIndex, Integer pageSize, String sort, String sortOrder) {
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//获取登录人信息
        if (clueFollowQO.getIsAdmin() == 1) {
            if (!CommonUtils.isAdmin(userAccount.getUserId())) {
                clueFollowQO.setCompanyId(userAccount.getCompanyId());
            }
        } else if (clueFollowQO.getIsAdmin() == 2) {
            clueFollowQO.setCreatePeopleId(userAccount.getAccountId());
        }
        //排序
        StringBuilder order = new StringBuilder();
        if (!StringUtils.isBlank(sort) && !StringUtils.isBlank(sortOrder)) {
            switch (sort) {
                case "createTm": {
                    order.append("create_tm ").append(sortOrder);//创建时间
                }
                break;
                case "customerIntention": {
                    order.append("customer_intention ").append(sortOrder);//意向度
                }
                break;
                case "followTm": {
                    order.append("follow_tm ").append(sortOrder);//跟进时间
                }
                break;
                case "tag": {
                    order.append("tag ").append(sortOrder);//标签
                }
                break;
                default:
                    break;
            }
        }

        Integer dateUnit = 0;
        if (!StringUtils.isBlank(clueFollowQO.getDateType())) {
            if ("thisDay".equals(clueFollowQO.getDateType())) {
                //今天
                dateUnit = 1;
            }
            if ("thisWeek".equals(clueFollowQO.getDateType())) {
                //本月
                dateUnit = 2;
            }
            if ("thisMonth".equals(clueFollowQO.getDateType())) {
                //本周
                dateUnit = 3;
            }
            if ("thisYear".equals(clueFollowQO.getDateType())) {
                //本年
                dateUnit = 4;
            }
        }

        List<ClueFollowVO> voList = clueFollowDbService.selectClueFollowPageList(clueFollowQO, order.toString(), dateUnit);
        PageInfo<ClueFollowVO> pageInfo = new PageInfo<>(voList);
        return new DhPageInfo<ClueFollowVO>(pageInfo, voList);
    }

    /**
     * 获取通话录音
     *
     * @param followId
     * @return
     */
    @Override
    public String getCallRecord(String followId) {
        String callRecordByFollowId = clueFollowDbService.getCallRecordByFollowId(followId);
        return callFormService.getSecretUrl(callRecordByFollowId);
    }

    /**
     * 图表数据获取
     *
     * @param dateUnit---本周1/本月2/上月3
     * @param startTimeStr           开始日期
     * @param endTimeStr             结束日期
     * @return
     * @Author renshaorong
     * @Date 2021/4/12
     */
    @Override
    public List<ClueFollowChartVO> selectClueFollowChartVOList(int dateUnit, String startTimeStr, String endTimeStr) {
        List<Date> dateList = this.formatTimeStr(startTimeStr, endTimeStr);
        String userAccountId = this.getUserAccountId();
        try {
            switch (dateUnit) {
                case 1: { //本周
                    List<ClueFollowChartVO> redisObject = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_TABLE_KEY + userAccountId, ClueFollowChartVO.class);
                    if (redisObject == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_TABLE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    return redisObject;
                }
                case 2: { //本月
                    List<ClueFollowChartVO> redisObject = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_TABLE_KEY + userAccountId, ClueFollowChartVO.class);
                    if (redisObject == null) {
                        log.error("key为" + MONTH_FOLLOW_TABLE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    return redisObject;
                }
                case 3: { //上月
                    List<ClueFollowChartVO> redisObject = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_TABLE_KEY + userAccountId, ClueFollowChartVO.class);
                    if (redisObject == null) {
                        log.error("key为" + LAST_MONTH_FOLLOW_TABLE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    return redisObject;
                }
                default:
                    throw new Exception();
            }
        } catch (Exception e) {
            log.error("跟进报表中 selectClueFollowChartVOList 方法捕获异常，此处数据从数据库中读取，请检查异常");
            return clueFollowDbService.selectClueFollowChartVOList(dateUnit, dateList.get(0), dateList.get(1), userAccountId);
        }
    }

    /**
     * 图表数据获取
     */
    @Override
    public List<ClueFollowChartVO> selectAdminClueFollowChartVOList(String startTimeStr, String endTimeStr) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        String companyId = userAccount.getCompanyId();

        return clueFollowDbService.selectAdminClueFollowChartVOList(startTimeStr, endTimeStr, companyId);
    }

    /**
     * 折线图数据获取
     *
     * @param dateUnit---本周1/本月2/上月3
     * @param startTimeStr           开始日期
     * @param endTimeStr             结束日期
     * @return
     * @Author renshaorong
     * @Date 2021/4/13
     */
    @Override
    public Map<String, Object> getPolyLine(Integer dateUnit, String startTimeStr, String endTimeStr) {
        List<Date> dateList = this.formatTimeStr(startTimeStr, endTimeStr);
        Date startTime = dateList.get(0);
        Date endTime = dateList.get(1);

        String userAccountId = getUserAccountId();

        try {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("type" , this.getPolyLineFollowTypeList());//折线类型
            switch (dateUnit) {
                case 1: { //本周
                    //time
                    List<String> days = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_DAY_KEY, String.class);
                    if (days == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_DAY_KEY + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：online
                    List<Integer> online = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_NUMBER_ONLINE_KEY + userAccountId, Integer.class);
                    if (online == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_NUMBER_ONLINE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：offline
                    List<Integer> offline = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_NUMBER_OFFLINE_KEY + userAccountId, Integer.class);
                    if (offline == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_NUMBER_OFFLINE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：visit
                    List<Integer> visit = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_NUMBER_VISIT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_NUMBER_VISIT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：wecat
                    List<Integer> wecat = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_NUMBER_WECAT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_NUMBER_WECAT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：acvisit
                    List<Integer> acvisit = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_NUMBER_ACVISIT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_NUMBER_ACVISIT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：mail
                    List<Integer> mail = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_FOLLOW_NUMBER_MAIL_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + WEEK_FOLLOW_NUMBER_MAIL_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    resultMap.put("time" , days);//时间轴
                    //跟进方式：1-线上电话；2-拜访 3-微信 4-线下电话 5-邮箱 6-陪访
                    resultMap.put("online" , online);//线上电话数据
                    resultMap.put("offline" , offline);//线下电话数据
                    resultMap.put("visit" , visit);//拜访数据
                    resultMap.put("wecat" , wecat);//微信数据
                    resultMap.put("acvisit" , acvisit);//陪访数据
                    resultMap.put("mail" , mail);//邮件数据

                    return resultMap;
                }
                case 2: { //本月
                    //time
                    List<String> days = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_DAY_KEY, String.class);
                    if (days == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_DAY_KEY + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：online
                    List<Integer> online = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_NUMBER_ONLINE_KEY + userAccountId, Integer.class);
                    if (online == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_FOLLOW_NUMBER_ONLINE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：offline
                    List<Integer> offline = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_NUMBER_OFFLINE_KEY + userAccountId, Integer.class);
                    if (offline == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_FOLLOW_NUMBER_OFFLINE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：visit
                    List<Integer> visit = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_NUMBER_VISIT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_FOLLOW_NUMBER_VISIT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：wecat
                    List<Integer> wecat = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_NUMBER_WECAT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_FOLLOW_NUMBER_WECAT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：acvisit
                    List<Integer> acvisit = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_NUMBER_ACVISIT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_FOLLOW_NUMBER_ACVISIT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：mail
                    List<Integer> mail = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_FOLLOW_NUMBER_MAIL_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + MONTH_FOLLOW_NUMBER_MAIL_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    resultMap.put("time" , days);//时间轴
                    //跟进方式：1-线上电话；2-拜访 3-微信 4-线下电话 5-邮箱 6-陪访
                    resultMap.put("online" , online);//线上电话数据
                    resultMap.put("offline" , offline);//线下电话数据
                    resultMap.put("visit" , visit);//拜访数据
                    resultMap.put("wecat" , wecat);//微信数据
                    resultMap.put("acvisit" , acvisit);//陪访数据
                    resultMap.put("mail" , mail);//邮件数据

                    return resultMap;
                }
                case 3: { //上月
                    //time
                    List<String> days = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_DAY_KEY, String.class);
                    if (days == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_DAY_KEY + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：online
                    List<Integer> online = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_NUMBER_ONLINE_KEY + userAccountId, Integer.class);
                    if (online == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_FOLLOW_NUMBER_ONLINE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：offline
                    List<Integer> offline = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_NUMBER_OFFLINE_KEY + userAccountId, Integer.class);
                    if (offline == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_FOLLOW_NUMBER_OFFLINE_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：visit
                    List<Integer> visit = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_NUMBER_VISIT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_FOLLOW_NUMBER_VISIT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：wecat
                    List<Integer> wecat = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_NUMBER_WECAT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_FOLLOW_NUMBER_WECAT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：acvisit
                    List<Integer> acvisit = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_NUMBER_ACVISIT_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_FOLLOW_NUMBER_ACVISIT_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }

                    //跟进方式：mail
                    List<Integer> mail = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_FOLLOW_NUMBER_MAIL_KEY + userAccountId, Integer.class);
                    if (visit == null) { // redis中无数据，抛出异常，从数据库中读取数据
                        log.error("key为" + LAST_MONTH_FOLLOW_NUMBER_MAIL_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    resultMap.put("time" , days);//时间轴
                    //跟进方式：1-线上电话；2-拜访 3-微信 4-线下电话 5-邮箱 6-陪访
                    resultMap.put("online" , online);//线上电话数据
                    resultMap.put("offline" , offline);//线下电话数据
                    resultMap.put("visit" , visit);//拜访数据
                    resultMap.put("wecat" , wecat);//微信数据
                    resultMap.put("acvisit" , acvisit);//陪访数据
                    resultMap.put("mail" , mail);//邮件数据

                    return resultMap;
                }
                default:
                    throw new Exception();
            }
        } catch (Exception e) {
            log.error("跟进报表中 getPolyLine 方法捕获异常，此处数据从数据库中读取，请检查异常");
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("time" , clueFollowDbService.getTimeList(dateUnit, startTime, endTime));//时间轴
            resultMap.put("type" , this.getPolyLineFollowTypeList());//折线类型
            //跟进方式：1-线上电话；2-拜访 3-微信 4-线下电话 5-邮箱 6-陪访
            resultMap.put("online" , clueFollowDbService.getFollowWayDataList(dateUnit, startTime, endTime, 1, userAccountId));//线上电话数据
            resultMap.put("offline" , clueFollowDbService.getFollowWayDataList(dateUnit, startTime, endTime, 4, userAccountId));//线下电话数据
            resultMap.put("visit" , clueFollowDbService.getFollowWayDataList(dateUnit, startTime, endTime, 2, userAccountId));//拜访数据
            resultMap.put("wecat" , clueFollowDbService.getFollowWayDataList(dateUnit, startTime, endTime, 3, userAccountId));//微信数据
            resultMap.put("acvisit" , clueFollowDbService.getFollowWayDataList(dateUnit, startTime, endTime, 6, userAccountId));//陪访数据
            resultMap.put("mail" , clueFollowDbService.getFollowWayDataList(dateUnit, startTime, endTime, 5, userAccountId));//邮件数据
            return resultMap;
        }
    }

    /**
     * 普通管理员 - 折线图数据获取
     *
     * @param startTimeStr 开始日期
     * @param endTimeStr   结束日期
     */
    @Override
    public Map<String, Object> getAdminPolyLine(String startTimeStr, String endTimeStr) {

        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        String companyId = userAccount.getCompanyId();

        Map<String, Object> resultMap = new HashMap<>();

        List<String> monthBetween = DateUtil.getMonthBetween(startTimeStr, endTimeStr);

        resultMap.put("time" , monthBetween);//时间轴
        resultMap.put("type" , this.getPolyLineFollowTypeList());//折线类型
        //跟进方式：1-线上电话；2-拜访 3-微信 4-线下电话 5-邮箱 6-陪访
        resultMap.put("online" , clueFollowDbService.getFollowWayDataListByCompanyId(startTimeStr, endTimeStr, 1, companyId));//线上电话数据
        resultMap.put("offline" , clueFollowDbService.getFollowWayDataListByCompanyId(startTimeStr, endTimeStr, 4, companyId));//线下电话数据
        resultMap.put("visit" , clueFollowDbService.getFollowWayDataListByCompanyId(startTimeStr, endTimeStr, 2, companyId));//拜访数据
        resultMap.put("wecat" , clueFollowDbService.getFollowWayDataListByCompanyId(startTimeStr, endTimeStr, 3, companyId));//微信数据
        resultMap.put("acvisit" , clueFollowDbService.getFollowWayDataListByCompanyId(startTimeStr, endTimeStr, 6, companyId));//陪访数据
        resultMap.put("mail" , clueFollowDbService.getFollowWayDataListByCompanyId(startTimeStr, endTimeStr, 5, companyId));//邮件数据

        return resultMap;
    }

    /**
     * 总跟进次数饼状图数据获取
     *
     * @param dateUnit---本周1/本月2/上月3
     * @param startTimeStr           开始日期
     * @param endTimeStr             结束日期
     * @return
     * @Author renshaorong
     * @Date 2021/4/14
     */
    @Override
    public List<Map> getNumPieData(Integer dateUnit, String startTimeStr, String endTimeStr) {
        List<Date> dateList = this.formatTimeStr(startTimeStr, endTimeStr);
        String userAccountId = getUserAccountId();
        try {
            switch (dateUnit) {
                case 1: {
                    List<Map> weekList = ValueRMapper.getRedisObjectList(stringRedisTemplate, WEEK_TOTAL_FOLLOW_NUMBER_KEY + userAccountId, Map.class);
                    if (weekList == null) {
                        log.error("key为" + WEEK_TOTAL_FOLLOW_NUMBER_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    return weekList;
                }
                case 2: {
                    List<Map> monthList = ValueRMapper.getRedisObjectList(stringRedisTemplate, MONTH_TOTAL_FOLLOW_NUMBER_KEY + userAccountId, Map.class);
                    if (monthList == null) {
                        log.error("key为" + MONTH_TOTAL_FOLLOW_NUMBER_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    return monthList;
                }
                case 3: {
                    List<Map> lastMonthList = ValueRMapper.getRedisObjectList(stringRedisTemplate, LAST_MONTH_TOTAL_FOLLOW_NUMBER_KEY + userAccountId, Map.class);
                    if (lastMonthList == null) {
                        log.error("key为" + LAST_MONTH_TOTAL_FOLLOW_NUMBER_KEY + userAccountId + "的值不存在");
                        throw new Exception();
                    }
                    return lastMonthList;
                }
                default:
                    throw new Exception();
            }
        } catch (Exception e) {
            return clueFollowDbService.getNumPieData(dateUnit, dateList.get(0), dateList.get(1), userAccountId);
        }
    }

    /**
     * 总跟进次数饼状图数据获取
     */
    @Override
    public List<Map> getAdminNumPieData(String startTimeStr, String endTimeStr) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        return clueFollowDbService.getAdminNumPieData(startTimeStr, endTimeStr, userAccount.getCompanyId());
    }

    /**
     * 获取商机状态饼状图数据
     *
     * @param dateUnit
     * @param startTimeStr
     * @param endTimeStr
     * @return
     * @Author renshaorong
     * @Date 2021/4/14
     */
    @Override
    public List<Map<String, Object>> getBusinessStatusData(Integer dateUnit, String startTimeStr, String endTimeStr, Integer type) {
        List<Date> dateList = this.formatTimeStr(startTimeStr, endTimeStr);
        String userAccountId = getUserAccountId();
        return clueFollowDbService.getBusinessStatusData(dateUnit, dateList.get(0), dateList.get(1), type, userAccountId);
    }

    /**
     * 获取过程状态饼状图数据
     *
     * @param dateUnit
     * @param startTimeStr
     * @param endTimeStr
     * @return
     * @Author renshaorong
     * @Date 2021/4/14
     */
    @Override
    public List<Map<String, Object>> getProcessStatusData(Integer dateUnit, String startTimeStr, String endTimeStr, Integer type) {
        List<Date> dateList = this.formatTimeStr(startTimeStr, endTimeStr);
        String userAccountId = getUserAccountId();
        return clueFollowDbService.getProcessStatusData(dateUnit, dateList.get(0), dateList.get(1), type, userAccountId);
    }

    @Override
    public List<Map<String, Object>> getAdminProcessStatusData(String startTimeStr, String endTimeStr, Integer type) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();

        return clueFollowDbService.getAdminProcessStatusData(startTimeStr, endTimeStr, type, userAccount.getCompanyId());
    }

    /**
     * 查询联系人最新的一条跟进记录
     *
     * @param contactId 联系人id
     * @return
     */
    @Override
    public List<ClueFollow> getClueFollowByContactId(String contactId) {
        return clueFollowDbService.getClueFollowByContactId(contactId);
    }

    /**
     * 获取跟进类型List（用于折线图的多条折线）
     *
     * @return
     * @Author renshaorong
     * @Date 2021/4/13
     */
    public List<String> getPolyLineFollowTypeList() {
        List<String> polyLineFollowTypeList = new ArrayList<>();
        polyLineFollowTypeList.add("线上电话");
        polyLineFollowTypeList.add("线下电话");
        polyLineFollowTypeList.add("拜访");
        polyLineFollowTypeList.add("微信");
        polyLineFollowTypeList.add("陪访");
        polyLineFollowTypeList.add("邮件");
        return polyLineFollowTypeList;
    }

    /**
     * 获取当前登陆用户的id
     *
     * @return
     * @Author renshaorong
     * @Date 2021/4/15
     */
    public String getUserAccountId() {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        return userAccount.getAccountId();
    }

    /**
     * 客户线上跟进
     *
     * @param customerOnlineFollowQO -线上跟进参数
     * @return {@link {java.lang.Boolean}}
     * @Author pym
     * @Date 2021/4/15 8:59
     */
    @Override
    public String customerOnlineFollowUp(CustomerOnlineFollowQO customerOnlineFollowQO) {
        Boolean result = false;
        String clueFollowId = "";
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        String accountId = userAccount.getAccountId();
        String companyId = userAccount.getCompanyId();
        String customerId = customerOnlineFollowQO.getCustomerId();
        int callDuration = customerOnlineFollowQO.getCallDuration();
        String contactId = customerOnlineFollowQO.getContactId();
        String contactInformation = customerOnlineFollowQO.getContactInformation();
        Integer followSource = customerOnlineFollowQO.getFollowSource();
        if (!StringUtils.isBlank(customerId)) {
            if (callDuration > 0) {//通话时长
                ClueFollowQO clueFollowQO = getClueFollowQO(customerOnlineFollowQO);
                //跟进表插数据
                clueFollowId = addClueFollow(clueFollowQO);
                if (StringUtils.isBlank(contactId)) {
                    customerOnlineFollowQO.setContactId(clueFollowQO.getContactId());
                }
            }
            if (StringUtils.isNotBlank(contactInformation)) {
                CallForm callForm = getCallForm(customerOnlineFollowQO, accountId, companyId, clueFollowId);
                //呼叫表单插数据
                result = callFormDbService.insertCallForm(callForm);
            }
        } else {
            if (callDuration > 0) {//通话时长
                if (followSource != null && (followSource == 0 || followSource == 2)) {
                    ClueFollowQO clueFollowQO = getClueFollowQO(customerOnlineFollowQO);
                    //跟进表插数据
                    clueFollowId = addClueFollow(clueFollowQO);
                } else {
                    //Contact contact = contactService.getContactByContactInfoAndId(contactInformation, accountId);
                    ContactInformationVO contact = contactInformationService.getContactInformationByContactInfoAndId(contactInformation, accountId);
                    String customerIdStr = contact != null ? contact.getCustomerId() : "";
                    if (StringUtils.isNotBlank(customerIdStr)) {
                        customerOnlineFollowQO.setCustomerId(customerIdStr);
                        customerOnlineFollowQO.setContactName(contact.getContactName());
                        customerOnlineFollowQO.setFollowSource(1);
                        ClueFollowQO clueFollowQO = getClueFollowQO(customerOnlineFollowQO);
                        //跟进表插数据
                        clueFollowId = addClueFollow(clueFollowQO);
                        if (StringUtils.isBlank(contactId)) {
                            customerOnlineFollowQO.setContactId(clueFollowQO.getContactId() != null ? clueFollowQO.getContactId() : contact.getContactId());
                        }
                    }
                }
            }
            if (StringUtils.isNotBlank(contactInformation)) {
                CallForm callForm = getCallForm(customerOnlineFollowQO, accountId, companyId, clueFollowId);
                //呼叫表单插数据
                result = callFormDbService.insertCallForm(callForm);
            }
        }
        return clueFollowId;
    }

    /**
     * 一机多用(线上跟进)
     * 备注(只操作跟进记录表)
     *
     * @param customerOnlineFollowQO
     * @return -String(返回跟进记录ID-用于保存一机多用跟进记录)
     * @author yincuimei
     */
    @Override
    public String oneMachineMultipleUses(CustomerOnlineFollowQO customerOnlineFollowQO) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//获取登录人信息
        String followId = "";
        if (customerOnlineFollowQO != null && customerOnlineFollowQO.getCallDuration() > 0) {//沟通时长大于0
            //封装跟进记录实体
            ClueFollow clueFollow = new ClueFollow();
            clueFollow.setClueFollowId(CommonUtils.getGUID());//主键
            clueFollow.setFollowWay(1);//跟进方式1-线上跟进
            String customerId = customerOnlineFollowQO.getCustomerId();//客户ID
            Integer followSource = customerOnlineFollowQO.getFollowSource();//跟进来源：0-线索跟进；1-客户跟进；2-单品客户跟进；3-联系人跟进；4-核实电话(数据在核实电话表)；5-商机;6-一机多用
            String contactPersonName = customerOnlineFollowQO.getContactName();//联系人
            String contactPersonPhone = customerOnlineFollowQO.getContactInformation();//联系人电话
            if (!StringUtils.isBlank(customerId)) {//客户ID
                clueFollow.setCustomerId(customerId);
            }
            if (followSource != null) {//跟进来源
                clueFollow.setFollowSource(followSource);
            }
            if (!StringUtils.isBlank(contactPersonName)) {//联系人
                clueFollow.setContactPersonName(contactPersonName);
            }
            if (!StringUtils.isBlank(contactPersonPhone)) {//联系电话
                clueFollow.setContactPersonPhone(contactPersonPhone);
            }
            clueFollow.setCommunicationTime(customerOnlineFollowQO.getCallDuration());//沟通时长(单位秒)
            clueFollow.setFollowTm(new Date());//跟进时间
            clueFollow.setCreatePeopleId(userAccount.getAccountId());//创建人ID
            clueFollow.setCreateTm(new Date());//创建时间
            clueFollow.setUpdatePeopleId(userAccount.getAccountId());//更新人
            clueFollow.setUpdateTm(new Date());//更新时间
            clueFollow.setDataSource(0);//0: 系统；1:导入
            clueFollow.setCompanyId(userAccount.getCompanyId());
            //新增跟进记录(cp_clue_follow)
            boolean result = clueFollowDbService.insertFollow(clueFollow);
            if (result) {//跟进表插入成功返回跟进记录ID
                followId = clueFollow.getClueFollowId();
            }
        }
        return followId;
    }

    /**
     * 客户跟进详情关键字分词
     *
     * @param followId
     */
    @Override
    public void followKeywordParticiple(String followId) {
        ClueFollow clueFollow = clueFollowDbService.selectClueFollowById(followId);
        StringBuilder sb = new StringBuilder();
        String str = ",";
        if (Objects.nonNull(clueFollow.getTag())) {
            sb.append(clueFollow.getTag() + str);
        }
        if (Objects.nonNull(clueFollow)) {
            KeyWordComputer key = new KeyWordComputer(10);
            Iterator it = key.computeArticleTfidf(clueFollow.getFollowDetail()).iterator();
            while (it.hasNext()) {
                Keyword key2 = (Keyword) it.next();
                sb.append(key2 + str);
            }
        }
        str = sb.toString();
        if (Objects.nonNull(str)) {
            str = str.substring(0, str.length() - 1);
            clueFollow.setTag(str);
            clueFollowDbService.updateClueFollow(clueFollow);
        }
    }

    /**
     * 跟进参数
     *
     * @param customerOnlineFollowQO -跟进参数
     * @return {@link {com.crm.model.qo.cluePoolManager.ClueFollowQO}}
     * @Author pym
     * @Date 2021/4/15 11:03
     */
    private ClueFollowQO getClueFollowQO(CustomerOnlineFollowQO customerOnlineFollowQO) {
        ClueFollowQO clueFollowQO = new ClueFollowQO();
        //clueFollowQO.setSingleProductCustomerId(customerOnlineFollowQO.getCustomerId());
        clueFollowQO.setSingleProductCustomerId(customerOnlineFollowQO.getSingleProductCustomerId());
        clueFollowQO.setCustomerId(customerOnlineFollowQO.getCustomerId());
        clueFollowQO.setContactName(customerOnlineFollowQO.getContactName());
        clueFollowQO.setContactInformation(customerOnlineFollowQO.getContactInformation());
        clueFollowQO.setFollowTm(new Date());
        clueFollowQO.setSource(customerOnlineFollowQO.getFollowSource() + "");
        clueFollowQO.setFollowWay(1);
        clueFollowQO.setFollowDetail(customerOnlineFollowQO.getFollowDetail());
        clueFollowQO.setCommunicationTime(customerOnlineFollowQO.getCallDuration());
        clueFollowQO.setContactId(customerOnlineFollowQO.getContactId());
        clueFollowQO.setClueId(customerOnlineFollowQO.getClueId());
        clueFollowQO.setCustomerType(customerOnlineFollowQO.getCustomerType());
        return clueFollowQO;
    }

    /**
     * @param customerOnlineFollowQO -线上跟进参数
     * @param accountId              -账号ID
     * @param companyId              -公司ID
     * @return {@link {com.crm.model.entity.callCenter.CallForm}}
     * @Author pym
     * @Date 2021/4/15 10:46
     */
    private CallForm getCallForm(CustomerOnlineFollowQO customerOnlineFollowQO, String accountId, String companyId, String clueFollowId) {
        CallForm callForm = new CallForm();
        String contactId = customerOnlineFollowQO.getContactId();
        String customerId = customerOnlineFollowQO.getCustomerId();
        String contactInformation = customerOnlineFollowQO.getContactInformation();
        String contactName = customerOnlineFollowQO.getContactName();
        callForm.setFormId(CommonUtils.getGUID());
        if (StringUtils.isBlank(contactId) && customerOnlineFollowQO.getFollowSource() != null
                && customerOnlineFollowQO.getFollowSource() == 1 && StringUtils.isNotBlank(contactInformation)) {
            Contact contact = contactDbService.getContact(customerId, contactInformation);
            contactId = contact != null ? contact.getContactId() : "";
        }
        callForm.setContactPersonId(contactId);
        callForm.setContactName(contactName);
        callForm.setContactPhone(contactInformation);
        callForm.setContactSource(customerOnlineFollowQO.getFollowSource());
        callForm.setCustomerId(customerId);
        callForm.setCompanyId(companyId);
        callForm.setCreateTm(new Date());
        callForm.setUserId(accountId);
        int callDuration = customerOnlineFollowQO.getCallDuration();
        callForm.setCallDuration(customerOnlineFollowQO.getCallDuration());
        callForm.setDeleteStatus(Short.parseShort(String.valueOf(StatusCodeEnum.NORMAL_CODE.getState())));
        callForm.setUpdatePeopleId(accountId);
        callForm.setUpdateTm(new Date());
        if (callDuration > 0) {
            callForm.setCallResult((byte) 1);
        } else {
            callForm.setCallResult((byte) 2);
        }
        callForm.setCallRecord(customerOnlineFollowQO.getCallRecord());
        callForm.setFollowId(clueFollowId);
        return callForm;
    }

    /**
     * 格式化返回时间字符串，结束时间为空时给当日
     *
     * @param startTimeStr
     * @param endTimeStr
     * @return
     * @Author renshaorong
     * @Date 2021/4/15
     */
    public List<Date> formatTimeStr(String startTimeStr, String endTimeStr) {
        List<Date> result = new ArrayList<>(2);
        Date startTime = DateUtil.parseDate(startTimeStr);
        Date endTime = null;
        if (!StringUtils.isEmpty(endTimeStr)) {
            endTime = DateUtil.parseDate(endTimeStr);
        } else {
            endTime = DateUtil.getTodayTime();
        }
        result.add(startTime);
        result.add(endTime);
        return result;
    }


    /**
     * @Description: 跟进记录导入
     * @Param: [file]
     * @Return: com.crm.common.model.DataResponse
     * @Author: lixq-f
     * @Date: 2021/6/8
     **/
    @Override
    public void clueFollowImportExcel(MultipartFile file) {
        List<ClueFollowRecordVO> recordList = null;
        try {
            //recordList = ExcelUtils.excelToList(file, ClueFollowRecordVO.class, true, 0);
        } catch (Exception e) {
            throw new BizBaseException("文档解析失败" + e.getMessage());
        }
        if (CollectionUtils.isEmpty(recordList)) {
            return;
        }
        //客户名称为空的数据不导入
        recordList = recordList.stream()
                .filter(r -> StringUtils.isNotEmpty(r.getCustomerName()))
                .collect(Collectors.toList());
        log.info("clueFollowImportExcel->recordList : {}" , JSON.toJSONString(recordList));

        List<ClueFollow> followList = Lists.newArrayList();
        for (ClueFollowRecordVO recordVO : recordList) {

        }

        clueFollowDbService.batchInsert(followList);
    }


    /**
     * @Description: 下载模板
     * @Param: []
     * @Return: void
     * @Author: lixq-f
     * @Date: 2021/6/8
     **/
    @Override
    public void downTemplate(HttpServletRequest req, HttpServletResponse resp) {
        InputStream in = null;
        OutputStream out = null;
        String path = "";
        try {
            //获取要下载的模板名称
            String fileName = "followRecord.xlsx";
            String osName = System.getProperty("os.name");
            if (osName.toLowerCase().startsWith("win")) {
                path = Thread.currentThread().getContextClassLoader().getResource("").getPath() + PathUtil.getDownPath() + "followRecord.xlsx";
            } else {
                path = PathUtil.getDownPath() + "followRecord.xlsx";
            }
            fileName = new java.net.URLDecoder().decode(fileName, "utf-8");
            resp.setContentType("application/octet-stream;charset=UTF-8");
            resp.setHeader("Content-Disposition" , "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), "iso8859-1"));
            //以流的形式下载文件
            in = new BufferedInputStream(new FileInputStream(path));
            //excel类型为xlsx下面对象用XSSFWorkbook，xls类型对象用HSSFWorkbook
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(in);
            out = new BufferedOutputStream(resp.getOutputStream());
            xssfWorkbook.write(out);
            out.flush();
        } catch (Exception e) {
            log.error("downTemplate :" , e);
            throw new BaseException("导入模板下载失败！");
        } finally {
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 导入跟进记录
     *
     * @param list
     * @param companyId
     * @return
     */
    @Override
    public JSONObject importFollow(List<ImportFollowVO> list, String companyId) {
        UserAccount loginUserAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        //返回的结果集
        JSONObject jsonObject = new JSONObject();
        //导入数量
        int importNum = 0;
        //重复的行数
        String repeatIdStr = "";
        //失败行数
        String importFailIdStr = "";

        if (list.size() > 0) {
            int count = 300;                   //一个线程处理300条数据
            int listSize = list.size();        //数据集合大小
            int runSize = (listSize / count) + 1;  //开启的线程数
            //int runSize = importExportService.calculateImportedThreads(listSize);

            List<ImportFollowVO> newlist = null;       //存放每个线程的执行数据

            ExecutorService executor = Executors.newCachedThreadPool();
            //创建两个个计数器
            CountDownLatch begin = new CountDownLatch(1);
            CountDownLatch end = new CountDownLatch(runSize);
            List<FutureTask<JSONObject>> taskList = new ArrayList<FutureTask<JSONObject>>();
            for (int i = 0; i < runSize; i++) {
                //计算每个线程执行的数据
                if ((i + 1) == runSize) {
                    int startIndex = (i * count);
                    int endIndex = list.size();
                    newlist = list.subList(startIndex, endIndex);
                } else {
                    int startIndex = (i * count);
                    int endIndex = (i + 1) * count;
                    if (endIndex > list.size()) {
                        endIndex = list.size();
                    }
                    newlist = list.subList(startIndex, endIndex);
                }
                FutureTask<JSONObject> futureTask = new FutureTask(new InsertFollowCallable(clueFollowDbService, newlist, begin, end, companyId, userAccountDbService, importFailureLogDbService, customerDbService));
                taskList.add(futureTask);
                executor.submit(futureTask);//submit返回一个Future，代表了即将要返回的结果
            }
            //重复的行数
            List<Integer> repeatIdList = new ArrayList();
            //失败行数
            List<Integer> importFailIdList = new ArrayList();

            for (int i = 0; i < taskList.size(); i++) {
                try {
                    // FutureTask的get方法会自动阻塞,直到获取计算结果为止
                    //导入数量
                    importNum = importNum + taskList.get(i).get().getInteger("importNum");

                    //重复数量
                    JSONArray repeatIdArray = taskList.get(i).get().getJSONArray("repeatIdStr");
                    for (int j = 0; j < repeatIdArray.size(); j++) {
                        int repeat = Integer.parseInt(repeatIdArray.get(j).toString());
                        repeatIdList.add(repeat + i * 300);
                    }

                    //失败数量
                    JSONArray importFailIdArray = taskList.get(i).get().getJSONArray("importFailIdStr");
                    for (int j = 0; j < importFailIdArray.size(); j++) {
                        int importFail = Integer.parseInt(importFailIdArray.get(j).toString());
                        importFailIdList.add(importFail + i * 300);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }

            // 关闭线程池
            executor.shutdown();

            jsonObject.put("importClueNum" , importNum);
            jsonObject.put("repeatIdStr" , repeatIdList);
            jsonObject.put("importFailIdStr" , importFailIdList);

        }
        return jsonObject;
    }

    /**
     * 线上电话  跟进详情修改
     *
     * @param clueFollow 跟进记录
     *                   yincuimei合用用户系统-跟进记录-跟进详情页面-可修改跟进详情(备注:如有修改请联调测试这个功能)
     * @return
     */
    @Override
    public Boolean updateClueFollow(ClueFollow clueFollow) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        clueFollow.setUpdateTm(new Date());
        clueFollow.setUpdatePeopleId(userAccount.getAccountId());
        return clueFollowDbService.updateClueFollow(clueFollow);
    }

    /**
     * 根据Excel同步数据库跟进类型为空的数据
     *
     * @param list
     * @param companyId
     */
    @Override
    public void importFollow2(List<ImportFollowVO> list, String companyId) {
        List<ClueFollowVO> followVOS = clueFollowDbService.selectClueFollowWayIsNull();
        for (int i = 0; i < list.size(); i++) {
            if (Objects.isNull(list.get(i).getCustomerName())) {
                list.get(i).setCustomerName("");
            }
            if (Objects.isNull(list.get(i).getFollowDetail())) {
                list.get(i).setFollowDetail("");
            }
            for (int k = 0; k < followVOS.size(); k++) {
                if (Objects.isNull(followVOS.get(k).getCustomerName())) {
                    followVOS.get(k).setCustomerName("");
                }
                if (Objects.isNull(followVOS.get(k).getFollowDetail())) {
                    followVOS.get(k).setFollowDetail("");
                }
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //log.info(list.get(i).getCreateTm()+":00 == "+formatter.format(followVOS.get(k).getCreateTm()));
                if ((list.get(i).getCreateTm() + ":00").equals(formatter.format(followVOS.get(k).getCreateTm()))
                        && list.get(i).getFollowDetail().equals(followVOS.get(k).getFollowDetail())
                        && list.get(i).getCustomerName().equals(followVOS.get(k).getCustomerName())) {
                    ClueFollow clueFollow = new ClueFollow();
                    clueFollow.setClueFollowId(followVOS.get(k).getClueFollowId());
                    clueFollow.setFollowWay(getFollowWay(list.get(i).getFollowWay()));
                    clueFollowDbService.updateClueFollow(clueFollow);
                }
            }
        }
    }

    private Integer getFollowWay(String followWay) {
        if ("电话".equals(followWay)) {
            return 1;
        }
        if ("上门".equals(followWay)) {
            return 2;
        }
        if ("微信".equals(followWay) || "QQ".equals(followWay)) {
            return 3;
        }
        if ("陪访".equals(followWay)) {
            return 6;
        }
        if ("邮件".equals(followWay)) {
            return 5;
        }
        if ("业务员手机".equals(followWay)) {
            return 4;
        }
        return null;
    }

}
